package org.iogame.action;

import com.alipay.remoting.AsyncContext;
import com.alipay.remoting.rpc.RpcCommandType;
import com.iohao.game.action.skeleton.core.ActionCommand;
import com.iohao.game.action.skeleton.core.flow.ActionAfter;
import com.iohao.game.action.skeleton.core.flow.FlowContext;
import com.iohao.game.action.skeleton.core.flow.attr.FlowAttr;
import com.iohao.game.action.skeleton.protocol.HeadMetadata;
import com.iohao.game.action.skeleton.protocol.ResponseMessage;
import lombok.extern.slf4j.Slf4j;
import org.iogame.data.DataMap;

import java.util.Objects;

/**
 * @author lc
 * @since 2022/10/26
 */
@Slf4j
public class TestActionAfter implements ActionAfter {

    @Override
    public void execute(final FlowContext flowContext) {
        final ResponseMessage response = flowContext.getResponse();

        AsyncContext asyncCtx = getAsyncContext(flowContext);

        if (Objects.isNull(asyncCtx)) {
            return;
        }

        // 有错误就响应给调用方
        if (response.hasError()) {
            // 异常消息发送到请求端
            String msg = flowContext.option(FlowAttr.msgException);
            response.setValidatorMsg(msg);
            asyncCtx.sendResponse(response);
            return;
        }

        // action 方法返回值是 void 的，不做处理
        ActionCommand actionCommand = flowContext.getActionCommand();
        if (actionCommand.getActionMethodReturnInfo().isVoid()) {
            return;
        }

        HeadMetadata metadata = response.getHeadMetadata();
        try {
            Class<?> name =  Class.forName(response.getDataClass());
            Object instance = name.getDeclaredConstructor().newInstance();
            log.info("发送路由: {}",metadata.getCmdMerge());
            DataMap.MERGE_MAP.put(metadata.getCmdMerge(), instance);
        } catch (Exception e) {
            log.info("错误了");
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        // 将数据回传给调用方
        asyncCtx.sendResponse(response);
    }

    private AsyncContext getAsyncContext(FlowContext flowContext) {
        ResponseMessage response = flowContext.getResponse();
        HeadMetadata headMetadata = response.getHeadMetadata();

        byte rpcCommandType = headMetadata.getRpcCommandType();

        if (rpcCommandType == RpcCommandType.REQUEST_ONEWAY) {
            return flowContext.option(FlowAttr.brokerClientContext);
        } else {
            return flowContext.option(FlowAttr.asyncContext);
        }
    }
}
